One problem encountered in multi-thread processor systems is that of how to manage limited shared resources among numerous threads of execution. This is no less true with a microprocessor hardware kernel. Management of resources may be accomplished entirely in software by a master thread or context. However, the resulting overhead is not desirable. In addition, managing the resources in software via a master context also effectively locks out any intermediate priority contexts, i.e., intermediate between the master thread and the thread(s) whose priority is being manipulated, while the manipulations are taking place.
Adding to the complexity of handling such shared resources is what is generally referred to as “priority inversion”. Priority inversion occurs when a standard semaphore is used to control some element of the system and the following sequence occurs:                a) A low priority thread takes the semaphore—it will only need to hold it for a small amount of execution time.        b) A high priority thread begins execution (preempting the low priority thread) and tries to take the same semaphore. It can't take it so it is now pending on the low priority thread.        c) A medium priority thread pre-empts the low priority context before it can release the semaphore.        
At the point that the medium priority thread pre-empts the low priority thread, the high priority thread ends up waiting on the execution of the medium priority thread, even though they are not trying to access the same device. This is referred to as priority inversion.
Research on priority inversion has yielded two solutions. The first is called priority inheritance. This technique mandates that a lower-priority thread inherit the priority of any higher-priority thread pending on a resource they share. This priority change should take place as soon as the high-priority thread begins to pend; it should end when the resource is released. This requires help from the operating system.
If priority inheritance were used in the scenario above, then at point ‘b)’, when the high priority thread goes pending on the low priority context, the low priority thread would ‘inherit’ the priority of the other thread until it released the semaphore and the medium priority thread would never come into play.
Another solution is what is called a priority ceiling. In this case, the resource that is being managed is assigned a priority, typically as high as or higher than the priority of any thread/context that may access it. When a thread takes control of the resource (takes the semaphore), it assumes the priority of the resource. In this fashion the inversion described above can not take place because the low priority context will have the high priority of the resource while it is using it.
The underlying problem is a software problem and in the past, the priority ceiling and priority inheritance solutions have been software solutions to the software problems.